package com.uum.admin.controller;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.uum.admin.pojo.entity.*;
import com.uum.admin.service.SysLoginLogService;
import com.uum.admin.service.SysUserService;
import com.uum.auth.api.LoginFeignClient;
import com.uum.common.core.constant.GlobalConstants;
import com.uum.common.core.constant.RedisConstants;
import com.uum.common.core.enums.UserCreateMethod;
import com.uum.common.core.result.Result;
import com.uum.mq.api.MqFeignClient;
import com.uum.web.util.IpUtils;
import com.uum.web.util.RequestUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Api(tags = "登陆接口")
@RestController
@RequestMapping("/api/v2/login")
@RequiredArgsConstructor
public class LoginController {

    private final Gitee gitee;

    private final RedisTemplate redisTemplate;
    private final PasswordEncoder passwordEncoder;
    private final SysUserService sysUserService;
    private final LoginFeignClient loginFeignClient;
    private final SysLoginLogService sysLoginLogService;
    private final MqFeignClient mqFeignClient;

    @ApiOperation(value = "后台管理系统登陆")
    @PostMapping("adminLogin")
    public Result adminLogin(@RequestBody Map<String, String> parameters, HttpServletRequest request) {
        Result result = loginFeignClient.postAccessToken(parameters);
        addLoginLog(result, request);
        return result;
    }

    @ApiOperation(value = "门户登陆")
    @PostMapping("webLogin")
    public Result webLogin(@RequestBody Map<String, String> parameters, HttpServletRequest request) {
        Result result = loginFeignClient.postAccessToken(parameters);
        addLoginLog(result, request);
        return result;
    }

    @ApiOperation(value = "获取码云登陆地址")
    @GetMapping("giteeUrl")
    public String giteeUrl() {
        String state = IdUtil.fastSimpleUUID();
        redisTemplate.opsForValue().set(RedisConstants.GITEE_STATE_KEY + state, 1,10, TimeUnit.MINUTES);
        String url = "https://gitee.com/oauth/authorize?client_id=" + gitee.getClient_id()
                + "&redirect_uri=" + gitee.getRedirect_uri()
                + "&response_type=code&state=" + state;
        return url;
    }


    @ApiOperation(value = "码云回调")
    @PostMapping("giteeCallback")
    public Result GiteeLogin(@RequestParam("code") String code, @RequestParam("state") String state, HttpServletRequest request) {
        //判断state
        if (!redisTemplate.hasKey(RedisConstants.GITEE_STATE_KEY + state)) {
            return Result.failed("非法State（有效期10分钟）");
        }
        //https://gitee.com/oauth/token?grant_type=authorization_code&code={code}&client_id={client_id}&redirect_uri={redirect_uri}&client_secret={client_secret}
        Map params = new HashMap();
        params.put("code", code);
        params.put("client_id", gitee.getClient_id());
        params.put("redirect_uri", gitee.getRedirect_uri());
        params.put("client_secret", gitee.getClient_secret());
        //获取access_token
        String post = HttpUtil.post("https://gitee.com/oauth/token?grant_type=authorization_code", params);
        String error = (String) JSONObject.parseObject(post).get("error");
        if (StrUtil.isNotBlank(error)) {
            String error_description = (String) JSONObject.parseObject(post).get("error_description");
            return Result.failed(error_description);
        }
        String access_token = (String) JSONObject.parseObject(post).get("access_token");
        //获取用户信息
        Map info = new HashMap();
        info.put("access_token", access_token);
        String userInfo = HttpUtil.get("https://gitee.com/api/v5/user", info);
        String username = "gitee-" + JSONObject.parseObject(userInfo).get("id");
        String nickname = (String) JSONObject.parseObject(userInfo).get("name");

        //判断是否存在数据库
        boolean isExist = sysUserService.getOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUsername, username).eq(SysUser::getNickname, nickname).eq(SysUser::getCreateMethod, UserCreateMethod.GITEE)) == null ? false : true;
        if (!isExist) {
            //不存在 保存到数据库
            SysUser user = new SysUser();
            //1.保存用户
            user.setUsername(username);
            user.setNickname(nickname);
            user.setPassword(passwordEncoder.encode("123456"));
            user.setStatus(1);
            user.setCreateMethod(UserCreateMethod.GITEE.name());
            //默认超级管理员为创建者
            user.setCreateUserId(1l);
            boolean isSave = sysUserService.save(user);
            if (isSave) {
                //2.赋予用户普通角色
                sysUserService.saveUserRole(user.getId(), GlobalConstants.USER_ROLE_CODE);
                //3.添加已读消息
                mqFeignClient.saveReadMsgByUser(user.getId());
            }
        }
        //生成token
        Map parameters = new HashMap<>();
        parameters.put("grant_type", "password");
        parameters.put("username", username);
        parameters.put("password", "123456");
        Result result = loginFeignClient.postAccessToken(parameters);
        //删除State
        redisTemplate.delete(RedisConstants.GITEE_STATE_KEY + state);
        //添加到日志
        addLoginLog(result, request);
        return result;
    }


    private void addLoginLog(Result result, HttpServletRequest request) {
        try {
            if (Result.isSuccess(result)) {
                //添加到登陆日志
                JSONObject jsonObject = JSONObject.parseObject(JSON.toJSONString(result.getData()));
                Integer userId = (Integer) jsonObject.get("userId");
                String client = RequestUtils.getOAuth2ClientId();
                String ip = IpUtils.getIpAddr(request);
                String cityInfo = IpUtils.getCityInfo(ip);
                Map<String, String> osAndBrowserInfo = IpUtils.getOsAndBrowserInfo(request);
                SysLoginLog loginLog = new SysLoginLog();
                loginLog.setIp(ip);
                loginLog.setUserId(Long.valueOf(userId));
                loginLog.setLocation(cityInfo);
                loginLog.setUserBrowser(osAndBrowserInfo.get("BROWSER"));
                loginLog.setUserSystem(osAndBrowserInfo.get("OS"));
                loginLog.setLoginTime(LocalDateTime.now());
                loginLog.setClient(client);
                sysLoginLogService.save(loginLog);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
